import plotly.graph_objects as go
import numpy as np
from dash import html, dcc
from dash.dependencies import Input, Output


def get_eigen_component():
    return html.Div([
        html.H1('特征值与特征向量可视化'),
        
        # 矩阵输入
        html.Div([
            html.Label('矩阵A:'),
            html.Div([
                dcc.Input(id='a11', type='number', value=1, style={'width': '50px'}),
                dcc.Input(id='a12', type='number', value=0, style={'width': '50px'}),
                dcc.Input(id='a13', type='number', value=0, style={'width': '50px'}),
            ], style={'margin': '10px'}),
            html.Div([
                dcc.Input(id='a21', type='number', value=0, style={'width': '50px'}),
                dcc.Input(id='a22', type='number', value=1, style={'width': '50px'}),
                dcc.Input(id='a23', type='number', value=0, style={'width': '50px'}),
            ], style={'margin': '10px'}),
            html.Div([
                dcc.Input(id='a31', type='number', value=0, style={'width': '50px'}),
                dcc.Input(id='a32', type='number', value=0, style={'width': '50px'}),
                dcc.Input(id='a33', type='number', value=1, style={'width': '50px'}),
            ], style={'margin': '10px'}),
        ]),
        
        # 数学原理与应用说明
        html.Div([
            html.H4('特征值与特征向量数学原理与应用'),
            
            html.Div([
                html.P('• 数学家: Augustin-Louis Cauchy (1789-1857) 和 Charles Hermite (1822-1901) 发展特征值理论'),
                html.P('• 原理: A·v = λ·v，其中A是方阵，v是非零特征向量，λ是特征值'),
                html.P('• 应用: 机器学习中的PCA降维、物理中的振动分析、图像处理中的特征提取'),
            ], style={'marginBottom': '20px', 'padding': '10px', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
        ]),
        
        # 结果显示
        dcc.Graph(id='eigen-plot'),
        html.Div(id='eigen-output')
    ])


def register_eigen_callbacks(app):
    @app.callback(
        [Output('eigen-plot', 'figure'),
         Output('eigen-output', 'children')],
        [Input('a11', 'value'), Input('a12', 'value'), Input('a13', 'value'),
         Input('a21', 'value'), Input('a22', 'value'), Input('a23', 'value'),
         Input('a31', 'value'), Input('a32', 'value'), Input('a33', 'value')]
    )
    def update_eigen_visualization(a11, a12, a13, a21, a22, a23, a31, a32, a33):
        A = np.array([[a11, a12, a13], [a21, a22, a23], [a31, a32, a33]])
        eigenvalues, eigenvectors = np.linalg.eig(A)
        
        # 创建可视化图形
        fig = go.Figure()
        
        # 添加特征向量可视化
        for i in range(len(eigenvalues)):
            if np.any(A[:,2] != 0) or np.any(eigenvectors[2,:] != 0):
                fig.add_trace(go.Scatter3d(
                    x=[0, eigenvectors[0,i]],
                    y=[0, eigenvectors[1,i]],
                    z=[0, eigenvectors[2,i]],
                    mode='lines',
                    line=dict(width=3),
                    name=f'特征向量 {i+1} (λ={eigenvalues[i]:.2f})'
                ))
            else:
                fig.add_trace(go.Scatter(
                    x=[0, eigenvectors[0,i]],
                    y=[0, eigenvectors[1,i]],
                    mode='lines',
                    line=dict(width=3),
                    name=f'特征向量 {i+1} (λ={eigenvalues[i]:.2f})'
                ))
        
        if np.any(A[:,2] != 0) or np.any(eigenvectors[2,:] != 0):
            fig.update_layout(
                scene=dict(
                    xaxis=dict(title='X轴', gridcolor='rgba(100, 100, 100, 0.5)', showbackground=True, backgroundcolor='rgba(230, 230, 230, 0.3)', gridwidth=2, showgrid=True, nticks=10),
                    yaxis=dict(title='Y轴', gridcolor='rgba(100, 100, 100, 0.5)', showbackground=True, backgroundcolor='rgba(230, 230, 230, 0.3)', gridwidth=2, showgrid=True, nticks=10),
                    zaxis=dict(title='Z轴', gridcolor='rgba(100, 100, 100, 0.5)', showbackground=True, backgroundcolor='rgba(230, 230, 230, 0.3)', gridwidth=2, showgrid=True, nticks=10),
                    camera=dict(
                        eye=dict(x=1.5, y=1.5, z=0.8),
                        up=dict(x=0, y=0, z=1)
                    )
                ),
                margin=dict(l=0, r=0, b=0, t=0),
                paper_bgcolor='white',
                plot_bgcolor='white',
                title='特征向量可视化'
            )
        else:
            fig.update_layout(
                title='特征向量可视化',
                xaxis_title='X轴',
                yaxis_title='Y轴'
            )
        
        return fig, f'特征值: {eigenvalues[0]:.2f}, {eigenvalues[1]:.2f}'